export interface Options {
  storage?: Storage;
}
const prefixId = "storage-form-";
const broadcastId = "form-synchronize-id";
const clearIdSign = "form-storage-clear-id";
const instanceList: FormStorage[] = [];
let isNeedInit = true;
export class FormStorage {
  channel: BroadcastChannel;
  saveTimer: number | null = null;
  saveData = this.debounce(this.saveDataToStorage, 3000);
  static storage: Storage = localStorage;
  static clearAll() {
    const keysToRemove = Object.keys(this).filter((key) =>
      key.startsWith(prefixId)
    );
    keysToRemove.forEach((key) => FormStorage.storage.removeItem(key));
    const channel = new BroadcastChannel(broadcastId);

    // 通知其他页面清空表单数据
    channel.postMessage(JSON.stringify({ formId: clearIdSign, data: null }));
  }
  constructor(
    public id: string,
    public formData: any,
    public options?: Options
  ) {
    this.id = prefixId + id;
    this.formData = formData.value ? formData.value : formData;
    this.channel = new BroadcastChannel(broadcastId);
    this.channel.onmessage = (e) => {
      const { formId, data } = JSON.parse(e.data);
      if (formId === this.id) {
        // 同步数据
        this.syncData(data);
      } else if (formId === clearIdSign) {
        // 清空数据
        this.clearData();
      }
    };
    this.loadDataFromStorage();
    instanceList.push(this);
    if (this.options?.storage) {
      FormStorage.storage = this.options?.storage;
    }
  }

  saveDataToStorage() {
    this.saveTimer && clearTimeout(this.saveTimer);
    const data = JSON.stringify(this.formData);
    FormStorage.storage.setItem(this.id, data);
    this.channel.postMessage(
      JSON.stringify({ formId: this.id, data: this.formData })
    );
  }

  // 将数据同步到表单中
  syncData(data: any) {
    if (data) {
      for (let key in data) {
        if (Object.prototype.hasOwnProperty.call(this.formData, key)) {
          this.formData[key] = data[key];
        }
      }
    }
  }

  // 从本地存储中加载数据
  loadDataFromStorage() {
    const data = FormStorage.storage.getItem(this.id);
    if (data) {
      const objData = JSON.parse(data);
      this.syncData(objData);
    }
  }

  clearData() {
    FormStorage.storage.removeItem(this.id);
    this.channel.postMessage(JSON.stringify({ formId: this.id, data: null }));
  }

  debounce(func: () => void, wait = 300) {
    return () => {
      this.saveTimer && clearTimeout(this.saveTimer);
      this.saveTimer = setTimeout(() => {
        func.apply(this);
      }, wait);
    };
  }
}

// 添加事件，只执行一次
if (isNeedInit) {
  isNeedInit = false;

  // 关闭事件时保存数据
  window.addEventListener("beforeunload", () => {
    instanceList.forEach((item) => item.saveDataToStorage());
  });

  // 切换页面时保存数据
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "hidden") {
      instanceList.forEach((item) => item.saveDataToStorage());
    }
  });
}
